/*
 * enc_gpio.cpp
 *
 *  Created on: 2018年11月8日
 *  Author: Degang.Wu (windragon@126.com)
 *  Desc:
 */

#include "public.h"
#include "enc_gpio.h"

int hienc_gpio_export(int pin)
{
	char 	gpio_val[SZ_1K];
	char	tmp[SZ_1K];

	if (!u::io::File::exists(SYSFS_GPIO_EXPORT))
	{
		return -1;
	}

	snprintf(gpio_val, sizeof(gpio_val), "/sys/class/gpio/gpio%d", pin);
	if (u::io::File::exists(gpio_val))
	{
		return 0;
	}

	int fd = open(SYSFS_GPIO_EXPORT, O_WRONLY);
	if (fd < 0)
	{
		BW_INFO("ERR: gpio open error\n");
		return -1;
	}

	int len = snprintf(tmp, sizeof(tmp), "%d", pin);
	if (write(fd, tmp, len) < 0)
	{
		close(fd);
		return -1;
	}
	close(fd);

	if (!u::io::File::exists(gpio_val))
	{
		return -1;
	}

	return 0;
}

int hienc_gpio_unexport(int pin)
{
	char buffer[64];
	int len;
	int fd;

	fd = open(SYSFS_GPIO_UNEXPORT, O_WRONLY);
	if (fd < 0)
	{
		return -1;
	}

	len = snprintf(buffer, sizeof(buffer), "%d", pin);
	if (write(fd, buffer, len) < 0)
	{
		close(fd);
		return -1;
	}

	close(fd);
	return 0;
}

int hienc_gpio_set_direction(int pin, int dir)
{
	static const char dir_str[] = "in\0out";
	char gpio_dir[SZ_1K];

	snprintf(gpio_dir, sizeof(gpio_dir), "/sys/class/gpio/gpio%d/direction", pin);
	int fd = open(gpio_dir, O_WRONLY);
	if (fd < 0)
	{
		return -1;
	}

	if (write(fd, &dir_str[dir == 0 ? 0 : 3], dir == 0 ? 2 : 3) < 0)
	{
		close(fd);
		return -1;
	}

	close(fd);
	return 0;
}


// none表示引脚为输入，不是中断引脚
// rising表示引脚为中断输入，上升沿触发
// falling表示引脚为中断输入，下降沿触发
// both表示引脚为中断输入，边沿触发
// 0-->none, 1-->rising, 2-->falling, 3-->both
int hienc_gpio_set_edge(int pin, int edge)
{
	const char dir_str[] = "none\0rising\0falling\0both";
	int ptr;
	char path[64];
	int fd;
	switch (edge)
	{
	case SYSFS_GPIO_EDGE_NONE:
		ptr = 0;
		break;
	case SYSFS_GPIO_EDGE_RISING:
		ptr = 5;
		break;
	case SYSFS_GPIO_EDGE_FALLING:
		ptr = 12;
		break;
	case SYSFS_GPIO_EDGE_BOTH:
		ptr = 20;
		break;
	default:
		ptr = 0;
	}

	snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/edge", pin);
	fd = open(path, O_WRONLY);
	if (fd < 0)
	{
		return -1;
	}

	if (write(fd, &dir_str[ptr], strlen(&dir_str[ptr])) < 0)
	{
		close(fd);
		return -1;
	}

	close(fd);
	return 0;
}


int hienc_gpio_write(int pin, int value)
{
	static const char values_str[] = "01";
	char path[64];
	int fd;

	snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/value", pin);
	fd = open(path, O_WRONLY);
	if (fd < 0)
	{
		return -1;
	}

	if (write(fd, &values_str[value == 0 ? 0 : 1], 1) < 0)
	{
		close(fd);
		return -1;
	}

	close(fd);
	return 0;
}

int hienc_gpio_read(int pin)
{
	char path[64];
	char value_str[3];
	int fd;

	snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/value", pin);
	fd = open(path, O_RDONLY);
	if (fd < 0)
	{
		return -1;
	}

	if (read(fd, value_str, 3) < 0)
	{
		close(fd);
		return -1;
	}

	close(fd);
	return (atoi(value_str));
}

#if 0
int main()
{
	int ret;

	if (hienc_gpio_export(2) < 0)
	{
		return -1;
	}

	ret = hienc_gpio_read(2);

	printf("ret=%d\n", ret);

	return 0;
}

#endif
